package logic

import (
	"context"
	"device-modbus/internal/biz/dal/dchan"
	"device-modbus/internal/biz/dao"
	"device-modbus/internal/biz/model"
	"device-modbus/internal/biz/repo"
	"errors"
	"time"

	"github.com/cloudwego/hertz/pkg/common/hlog"
	"github.com/cloudwego/hertz/pkg/common/json"
)

// CommandLogic 指令配置业务逻辑
type CommandLogic struct {
	cmdRepo    repo.CommandRepo
	deviceRepo repo.DeviceRepo
}

// NewCommandLogic 创建指令配置业务逻辑实例
func NewCommandLogic(cmdRepo repo.CommandRepo, deviceRepo repo.DeviceRepo) *CommandLogic {
	return &CommandLogic{
		cmdRepo:    cmdRepo,
		deviceRepo: deviceRepo,
	}
}

// 转换数据库模型到socket层配置模型
func (l *CommandLogic) toDataCollectionCommand(dbCmd *model.DeviceCommand) dao.DataCollectionCommand {
	params := dbCmd.Par
	//json字符串解析为map
	paramsMap := make(map[string]string)
	// 空字符串处理
	if params == "" {
		params = "{}"
	}
	if err := json.Unmarshal([]byte(params), &paramsMap); err != nil {
		hlog.Errorf("解析指令参数 %s 失败: %v", params, err)
	}
	// 转换数据库模型到socket层配置模型
	command := dao.DataCollectionCommand{
		Name:     dbCmd.Name,
		Command:  dbCmd.Command,
		Interval: time.Duration(dbCmd.IntervalTime) * time.Second,
		Enabled:  dbCmd.Enabled == 1,
		Timeout:  time.Duration(dbCmd.Timeout) * time.Second,
		Retry:    dbCmd.Retry,
		Sort:     dbCmd.Sort,
		Params:   paramsMap,
	}
	// 输出command
	hlog.Info("转换值：toDataCollectionCommand command: %v", command)
	return command
}

// 发送设备原始指令
func (l *CommandLogic) SendDeviceCommand(ctx context.Context, deviceID string, cmdName string) error {
	// 1. 获取设备指令配置
	dbCmd, err := l.cmdRepo.GetByDeviceAndName(ctx, deviceID, cmdName)
	if err != nil {
		return err
	}

	// 2. 转换为socket层指令格式
	socketCmd := l.toDataCollectionCommand(dbCmd)

	// 3. 发送指令到设备
	dchan.CommandsChan <- dao.ChanDataCollectionCommand{
		Iccid:   deviceID,
		Command: socketCmd,
	}

	return nil
}

// 转换数据库模型列表到socket层配置模型
func (l *CommandLogic) toDataCollectionConfig(dbCmds []*model.DeviceCommand) dao.DataCollectionConfig {
	commands := make(map[string]dao.DataCollectionCommand)
	for _, cmd := range dbCmds {
		commands[cmd.Name] = l.toDataCollectionCommand(cmd)
	}
	return dao.DataCollectionConfig{
		Enabled:       len(commands) > 0, // 只要有指令就启用采集
		Commands:      commands,
		MaxBufferSize: 100,
	}
}

// 获取设备的所有指令配置
func (l *CommandLogic) GetDeviceCommands(ctx context.Context, deviceID string) ([]*model.DeviceCommand, error) {
	// 排序：按Sort字段升序排序，确保按配置顺序执行
	return l.cmdRepo.ListByDeviceID(ctx, deviceID)
}

// 获取设备的指令配置（转换为socket层使用的格式）
func (l *CommandLogic) GetDeviceCollectionConfig(ctx context.Context, deviceID string) (dao.DataCollectionConfig, error) {
	// 1. 获取设备所有指令配置
	dbCmds, err := l.cmdRepo.ListByDeviceID(ctx, deviceID)
	if err != nil {
		// 输出err
		hlog.Error("GetDeviceCollectionConfig err: %v", err)
		return dao.DataCollectionConfig{}, err
	}

	config := l.toDataCollectionConfig(dbCmds)

	return config, nil
}

// 创建设备指令配置
func (l *CommandLogic) CreateDeviceCommand(ctx context.Context, cmd *model.DeviceCommand) error {
	// 检查是否已存在同名指令
	existing, err := l.cmdRepo.GetByDeviceAndName(ctx, cmd.DeviceID, cmd.Name)
	if err == nil && existing != nil {
		return errors.New("该指令名称已存在")
	}
	// 创建指令
	if err := l.cmdRepo.Create(ctx, cmd); err != nil {
		return err
	}
	// 如果设备在线，推送配置更新
	socketCmd := l.toDataCollectionCommand(cmd)
	device, _ := l.deviceRepo.GetByID(ctx, cmd.DeviceID)
	dchan.CommandsChan <- dao.ChanDataCollectionCommand{
		Iccid:   device.Iccid,
		Command: socketCmd,
	}

	return nil
}

// 批量创建设备指令配置
func (l *CommandLogic) BatchCreateDeviceCommands(ctx context.Context, cmds []*model.DeviceCommand) error {
	if len(cmds) == 0 {
		return errors.New("指令列表不能为空")
	}

	// 获取设备ID
	deviceID := cmds[0].DeviceID

	// 批量创建指令
	if err := l.cmdRepo.BatchCreate(ctx, cmds); err != nil {
		return err
	}

	// 如果设备在线，推送完整配置
	newCmds, err := l.cmdRepo.ListByDeviceID(ctx, deviceID)
	if err == nil {
		cfg := l.toDataCollectionConfig(newCmds)
		device, _ := l.deviceRepo.GetByID(ctx, deviceID)
		dchan.CfgChan <- dao.ChanDataCollectionConfig{
			Iccid: device.Iccid,
			Cfg:   cfg,
		}
	}

	return nil
}

// 更新设备指令配置
func (l *CommandLogic) UpdateDeviceCommand(ctx context.Context, cmd *model.DeviceCommand) error {
	// 检查指令是否存在
	existing, err := l.cmdRepo.GetByDeviceAndName(ctx, cmd.DeviceID, cmd.Name)
	if err != nil || existing == nil {
		return errors.New("指令不存在")
	}

	// 更新指令
	if err := l.cmdRepo.Update(ctx, cmd); err != nil {
		return err
	}

	// 如果设备在线，推送配置更新
	socketCmd := l.toDataCollectionCommand(cmd)
	device, _ := l.deviceRepo.GetByID(ctx, cmd.DeviceID)
	dchan.CommandsChan <- dao.ChanDataCollectionCommand{
		Iccid:   device.Iccid,
		Command: socketCmd,
	}

	return nil
}

// 删除设备指令配置
func (l *CommandLogic) DeleteDeviceCommand(ctx context.Context, deviceID, name string) error {
	device, _ := l.deviceRepo.GetByID(ctx, deviceID)

	// 检查指令是否存在
	existing, err := l.cmdRepo.GetByDeviceAndName(ctx, deviceID, name)
	if err != nil || existing == nil {
		return errors.New("指令不存在")
	}

	// 删除指令
	if err := l.cmdRepo.Delete(ctx, deviceID, name); err != nil {
		return err
	}

	// 如果设备在线，获取剩余指令并推送更新
	remainingCmds, err := l.cmdRepo.ListByDeviceID(ctx, deviceID)
	if err == nil {
		cfg := l.toDataCollectionConfig(remainingCmds)
		dchan.CfgChan <- dao.ChanDataCollectionConfig{
			Iccid: device.Iccid,
			Cfg:   cfg,
		}
	}

	return nil
}

// 启用/禁用设备指令
func (l *CommandLogic) ToggleCommandEnabled(ctx context.Context, deviceID string, name string, enabled int) error {
	device, _ := l.deviceRepo.GetByID(ctx, deviceID)

	// 获取指令
	cmd, err := l.cmdRepo.GetByDeviceAndName(ctx, deviceID, name)
	if err != nil || cmd == nil {
		return errors.New("指令不存在")
	}

	// 更新启用状态
	cmd.Enabled = 1
	if err := l.cmdRepo.Update(ctx, cmd); err != nil {
		return err
	}

	// 如果设备在线，推送配置更新
	socketCmd := l.toDataCollectionCommand(cmd)
	dchan.CommandsChan <- dao.ChanDataCollectionCommand{
		Iccid:   device.Iccid,
		Command: socketCmd,
	}

	return nil
}
